WPF replacement options for an animated gif or How to make a spinner?
Option 1 – Spin an image using a Storyboard
UPDATE: Check out this more recent post: A SpinningImage control in WPF
If your animation is just a single image that moves, such as a spinner, you can use a Storyboard to spin the single image.
Here is a spinner.png file (128×128) that I made really quickly in Paint.NET.
- Create a default WPF Application project in visual studio.
- Add the spinner.png image to the project (or use your own image).
- Add a Storyboard to the resources.
Here is the Xaml.
<Window x:Class="SpinAnImage.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="300" Width="300"> <Window.Resources> <Storyboard x:Key="Spin360" Storyboard.TargetName="Spinner" Storyboard.TargetProperty="RenderTransform.(RotateTransform.Angle)"> <DoubleAnimation From="0" To="360" BeginTime="0:0:0" Duration="0:0:2" RepeatBehavior="Forever" /> </Storyboard> </Window.Resources> <Grid> <Image Name="Spinner" Source="spinner.png" Width="128" Height="128" RenderTransformOrigin="0.5, 0.5"> <Image.Triggers> <EventTrigger RoutedEvent="FrameworkElement.Loaded"> <EventTrigger.Actions> <BeginStoryboard Storyboard="{StaticResource Spin360}" /> </EventTrigger.Actions> </EventTrigger> </Image.Triggers> <Image.RenderTransform> <RotateTransform Angle="0" /> </Image.RenderTransform> </Image> </Grid> </Window>
Here is the simple Visual Studio 2010 project:
Option 2 – Loop through images using a Storyboard
This option is the one you would use if you have multiple images. You can create a Storyboard that loops through all of your images. If you have a gif, you can extract each image and use them.
Here is a BlackSpinner1.png file (128×128) that I made really quickly in Paint.NET. Actually I made eight versions of this image, where the section that is gray changes in each image.
Here is how you configure your project to animate through these images.
- Create a default WPF Application project in visual studio.
- Add a folder to the project called Images.
- Add the images you want to loop through to the Images directory.
- Add a Storyboard to the resources.
Here is the Xaml.
<Window x:Class="SpinUsingMultipleImages.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Spinner using multiple images" Height="300" Width="300"> <Grid> <Grid.Resources> <Storyboard x:Key="BlackSpinnerStoryBoard"> <ObjectAnimationUsingKeyFrames Duration="0:0:2" Storyboard.TargetProperty="Source" RepeatBehavior="Forever"> <DiscreteObjectKeyFrame KeyTime="0:0:0"> <DiscreteObjectKeyFrame.Value> <BitmapImage UriSource="Images/BlackSpinner1.png"/> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> <DiscreteObjectKeyFrame KeyTime="0:0:0.25"> <DiscreteObjectKeyFrame.Value> <BitmapImage UriSource="Images/BlackSpinner2.png"/> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> <DiscreteObjectKeyFrame KeyTime="0:0:0.50"> <DiscreteObjectKeyFrame.Value> <BitmapImage UriSource="Images/BlackSpinner3.png"/> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> <DiscreteObjectKeyFrame KeyTime="0:0:0.75"> <DiscreteObjectKeyFrame.Value> <BitmapImage UriSource="Images/BlackSpinner4.png"/> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> <DiscreteObjectKeyFrame KeyTime="0:0:1"> <DiscreteObjectKeyFrame.Value> <BitmapImage UriSource="Images/BlackSpinner5.png"/> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> <DiscreteObjectKeyFrame KeyTime="0:0:1.25"> <DiscreteObjectKeyFrame.Value> <BitmapImage UriSource="Images/BlackSpinner6.png"/> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> <DiscreteObjectKeyFrame KeyTime="0:0:1.50"> <DiscreteObjectKeyFrame.Value> <BitmapImage UriSource="Images/BlackSpinner7.png"/> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> <DiscreteObjectKeyFrame KeyTime="0:0:1.75"> <DiscreteObjectKeyFrame.Value> <BitmapImage UriSource="Images/BlackSpinner8.png"/> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </Grid.Resources> <Image Name="BlackSpinner"> <Image.Triggers> <EventTrigger RoutedEvent="Image.Loaded"> <EventTrigger.Actions> <BeginStoryboard Storyboard="{StaticResource BlackSpinnerStoryBoard}" /> </EventTrigger.Actions> </EventTrigger> </Image.Triggers> </Image> </Grid> </Window>
Here is a sample project attached.
Great solution. Only problem I had was the gif I used had 30 frames and each frame only contained the bit that differed from the previous frame. Used paint.net to layer and save each complete png. Took a while but the result is exactly what I was after and really so easy to implement. Thank you.
Your welcome. 🙂
Nice solution!
[…] single best demonstration I found was at WPFSharp. It’s all-XAML, intuitive, and complete (which is very helpful for […]